package com.sinosoft.dsp.component.bpm.viewbean;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.model.SelectItem;
import javax.xml.namespace.QName;

import org.primefaces.model.DefaultTreeNode;

import com.sinosoft.dsp.component.bpm.exception.SinoBPMException;
import com.sinosoft.dsp.component.bpm.service.core.BpmSelectItemsService;
import com.sinosoft.dsp.component.bpm.util.BpmImageType;
import com.sinosoft.dsp.component.bpm.util.BpmStatusType;
import com.sinosoft.dsp.component.bpm.util.ProcessParse;
import com.sinosoft.dsp.func.entity.setting.system.role.RoleEntity;
import com.sinosoft.dsp.func.service.setting.system.role.IRoleService;
import com.sinosoft.dsp.platform.components.AbstractEditViewBean;
import com.sinosoft.dsp.platform.components.portal.input.picklist.SinoPickListModel;
import com.sinosoft.dsp.platform.utils.SinoManagedBean;
import com.sinosoft.dsp.security.services.SinoAuthenticator;
import com.sinosoft.dsp.security.utils.AuthenticationStatus;
import com.sinosoft.dsp.security.utils.PrivilegeType;
import com.sinosoft.dsp.system.core.exception.SinoException;
import com.sinosoft.dsp.system.to.IGenericTO;
import com.sinosoft.dsp.system.to.attribute.Attribute;
import com.sinosoft.dsp.system.to.helper.ToHelper;
import com.sinosoft.dsp.system.utils.Const;
import com.sinosoft.dsp.system.utils.DateUtils;

public class BpmAddEditDefineViewBean extends AbstractEditViewBean implements
		IBpmAddEditDefineViewBean {
	/**
	 * 基本属性
	 */
	// 流程编号(Long)
	public static final String FIELD_DEFINE_ID = "defineId";

	// 部署ID(Long)
	public static final String FIELD_DEPLOYMENT_ID = "deploymentId";

	// 包名称和资源
	public static final String FIELD_PARENT_NAME = "parentName";
	public static final String FIELD_PARENT_RESOURCE = "parentResource";

	// 流程标识
	public static final String FIELD_DEFINE_NAME = "defineName";

	// 原始资源名称
	public static final String FIELD_INIT_RESOURCE = "initResourceName";

	// 流程描述
	public static final String FIELD_DEFINE_DESC = "defineDesc";

	// 流程对应图标
	public static final String FIELD_DEFINE_ICON = "defineIcon";

	// 发布状态
	public static final String FIELD_DEFINE_STATUS = "defineStatus";

	// 帮助文档
	public static final String FIELD_DEFINE_DOC = "defineDoc";

	// 流程版本
	public static final String FIELD_DEFINE_VERSION = "defineVersion";

	// 流程创建者
	public static final String FIELD_CREATOR_ID = "creatorId";
	public static final String FIELD_CREATOR = "creator";

	// 流程创建时间
	public static final String FIELD_CREATE_TIME = "createTime";
	public static final String FIELD_CREATE_TIME_STR = "createTimeStr";

	// 流程最后更新者
	public static final String FIELD_LAST_UPDATOR_ID = "lastUpdatorId";
	public static final String FIELD_LAST_UPDATOR = "lastUpdator";

	// 流程最后更新时间
	public static final String FIELD_LAST_UPDATE_TIME = "lastUpdateTime";
	public static final String FIELD_LAST_UPDATE_TIME_STR = "lastUpdateTimeStr";

	/**
	 * 表单属性
	 */
	// 表单类别
	public static final String FIELD_FORM_TYPE = "formType";

	// 表单视图配置（表单配置引擎）
	public static final String FIELD_FORM_ID = "formId";

	// 表单视图配置（表单配置引擎）
	public static final String FIELD_FORM_PAGE_URL = "formPageUrl";

	// 表单视图帮助
	public static final String FIELD_FORM_HELP_DOC = "helpDoc";

	// 是否级联删除(boolean)
	public static final String FIELD_FORM_CASCADE = "cascade";

	/**
	 * 权限属性
	 */
	// 创建权限属性
	private SinoPickListModel<BpmPrivilegeObject> createPrivilegeModel = new SinoPickListModel<BpmPrivilegeObject>();

	// 查看权限属性
	private SinoPickListModel<BpmPrivilegeObject> viewPrivilegeModel = new SinoPickListModel<BpmPrivilegeObject>();

	// 管理权限属性
	private SinoPickListModel<BpmPrivilegeObject> managePrivilegeModel = new SinoPickListModel<BpmPrivilegeObject>();

	// 全局参数属性
	private List<BpmFieldObject> defineFields = new ArrayList<BpmFieldObject>();

	private BpmFieldObject[] selectedRows;

	public static final String[] FIELD_STRINGS = new String[] {
			FIELD_DEFINE_DESC, FIELD_DEFINE_ICON, FIELD_DEFINE_STATUS,
			FIELD_DEFINE_DOC, FIELD_CREATOR_ID, FIELD_CREATOR,
			FIELD_LAST_UPDATOR_ID, FIELD_LAST_UPDATOR, FIELD_FORM_TYPE,
			FIELD_FORM_ID, FIELD_FORM_PAGE_URL, FIELD_FORM_HELP_DOC };

	public static final String[] FIELD_DATES = new String[] {
			FIELD_CREATE_TIME, FIELD_LAST_UPDATE_TIME };

	public static final String[] FIELD_BOOLEANS = new String[] { FIELD_FORM_CASCADE };

	@SuppressWarnings("unchecked")
	@Override
	public void init(IGenericTO tos) throws SinoException {

		IBpmConfigViewBean dirViewBean = (IBpmConfigViewBean) this.getParent();
		Attribute<?> sIdAttr = ToHelper.getContentAttriubteByName(tos,
				"selectedId");

		SinoAuthenticator sa = SinoManagedBean.findBean("sinoAuthenticator");
		if (sa.getStatus() == AuthenticationStatus.FAILURE) {
			throw new SinoBPMException("请先登录系统");
		}

		IRoleService rs = SinoManagedBean.findBean("roleService");
		List<RoleEntity> roles = rs.findAll();
		if (roles != null) {
			for (RoleEntity re : roles) {
				BpmPrivilegeObject bp = new BpmPrivilegeObject();
				bp.setId(re.getRoleuuid());
				bp.setName(re.getRolename());
				bp.setType(PrivilegeType.DEFAULT_PRIVILEGE_TYPE.getKey());

				createPrivilegeModel.getSource().add(bp);
				viewPrivilegeModel.getSource().add(bp);
				managePrivilegeModel.getSource().add(bp);
			}
		}

		// 判断是更新还是添加
		Date now = new Date();
		// 父节点
		DefaultTreeNode ptn = dirViewBean.getCurrentNode();
		BpmConfigDataObject pdo = (BpmConfigDataObject) ptn.getData();

		if (sIdAttr == null || Const.isEmpty(sIdAttr.convertToString())) {

			this.addField(FIELD_DEPLOYMENT_ID, pdo.getDeploymentId());

			this.addField(FIELD_PARENT_NAME, (Const.isEmpty(pdo
					.getResourceName())) ? pdo.getName() : pdo
					.getResourceName());
			this.addField(FIELD_PARENT_RESOURCE, Const.NVL(pdo
					.getResourceName(), ""));

			this.addField(FIELD_DEFINE_VERSION, 0);

			this.addField(FIELD_CREATE_TIME, now);
			this.addField(FIELD_CREATE_TIME_STR, DateUtils.dat2str(now));

			this.addField(FIELD_CREATOR_ID, sa.getCurrentUser().getUseruuid());
			this.addField(FIELD_CREATOR, sa.getCurrentUser().getFullname());

			this.addField(FIELD_FORM_TYPE,
					BpmSelectItemsService.SELECT_ITEM_DEFINE_FORMTYPE_DEFAULT);

			this.addField(FIELD_FORM_CASCADE, false);
		} else {

			DefaultTreeNode tn = dirViewBean.getNode(sIdAttr.convertToString());
			BpmConfigDataObject bdo = (BpmConfigDataObject) tn.getData();

			this.addField(FIELD_DEFINE_NAME, bdo.getName());

			this.addField(FIELD_INIT_RESOURCE, bdo.getResourceName());

			this.addField(FIELD_DEPLOYMENT_ID, bdo.getDeploymentId());

			// 获得流程对象
			org.jbpm.xsdobject.Process p = ProcessParse.parseJpdlDefine(bdo
					.getDeploymentId(), bdo.getResourceName());

			this.addField(FIELD_PARENT_NAME, (Const.isEmpty(pdo
					.getResourceName())) ? pdo.getName() : pdo
					.getResourceName());
			this.addField(FIELD_PARENT_RESOURCE, Const.NVL(pdo
					.getResourceName(), ""));

			this.addField(FIELD_LAST_UPDATE_TIME, now);
			this.addField(FIELD_LAST_UPDATE_TIME_STR, DateUtils.dat2str(now));

			this.addField(FIELD_LAST_UPDATOR_ID, sa.getCurrentUser()
					.getUseruuid());
			this
					.addField(FIELD_LAST_UPDATOR, sa.getCurrentUser()
							.getFullname());

			// 附加参数
			// 版本
			int ver = 0;
			if (p.getVersion() != null) {
				ver = p.getVersion();
				ver++;
			}
			this.addField(FIELD_DEFINE_VERSION, ver);
			fromMap(p.getOtherAttributes());
		}
	}

	public List<SelectItem> getDefineIconItems() {
		return BpmImageType.defineIconItems;
	}

	public List<SelectItem> getDefineStatusItems() {
		return BpmStatusType.getStatusItems();
	}

	public String getDefineIconPath() {
		String icon = (String) this.getField(FIELD_DEFINE_ICON);

		if (Const.isEmpty(icon)) {
			icon = BpmImageType.defaultDefineIcon;
			this.addField(FIELD_DEFINE_ICON, icon);
		}
		return BpmImageType.getDefineIconPath(icon);
	}

	public List<SelectItem> getPrivilegeTypeItems() {
		return PrivilegeType.getSelectItems();
	}

	public SinoPickListModel<BpmPrivilegeObject> getCreatePrivilegeModel() {
		return createPrivilegeModel;
	}

	public void setCreatePrivilegeModel(
			SinoPickListModel<BpmPrivilegeObject> createPrivilegeModel) {
		this.createPrivilegeModel = createPrivilegeModel;
	}

	public SinoPickListModel<BpmPrivilegeObject> getViewPrivilegeModel() {
		return viewPrivilegeModel;
	}

	public void setViewPrivilegeModel(
			SinoPickListModel<BpmPrivilegeObject> viewPrivilegeModel) {
		this.viewPrivilegeModel = viewPrivilegeModel;
	}

	public SinoPickListModel<BpmPrivilegeObject> getManagePrivilegeModel() {
		return managePrivilegeModel;
	}

	public void setManagePrivilegeModel(
			SinoPickListModel<BpmPrivilegeObject> managePrivilegeModel) {
		this.managePrivilegeModel = managePrivilegeModel;
	}

	public List<BpmFieldObject> getDefineFields() {
		return defineFields;
	}

	public void setDefineFields(List<BpmFieldObject> defineFields) {
		this.defineFields = defineFields;
	}

	public void removeDefineField() {
		if (selectedRows != null && selectedRows.length > 0) {
			for (BpmFieldObject a : selectedRows) {
				this.defineFields.remove(a);
			}
		}
	}

	public void addDefineField() {
		this.defineFields.add(new BpmFieldObject());
	}

	public BpmFieldObject[] getSelectedRows() {
		return selectedRows;
	}

	public void setSelectedRows(BpmFieldObject[] selectedRows) {
		this.selectedRows = selectedRows;
	}

	/**
	 * 转换为映射对象
	 * 
	 * @return
	 * @throws SinoBPMException
	 */
	@Override
	public Map<QName, String> toMap() throws SinoBPMException {
		try {
			Map<QName, String> map = new HashMap<QName, String>();
			// Boolean型
			if (FIELD_BOOLEANS != null)
				for (String f : FIELD_BOOLEANS) {
					if (this.getFields().containsKey(f)) {
						if (this.getField(f) instanceof String) {
							map
									.put(QName.valueOf(f), (String) this
											.getField(f));
						} else if (this.getField(f) instanceof Boolean) {
							map.put(QName.valueOf(f), ((Boolean) this
									.getField(f)).toString());
						}
					}
				}

			// 字符串型
			if (FIELD_STRINGS != null)
				for (String f : FIELD_STRINGS) {
					if (this.getFields().containsKey(f)) {
						if (this.getField(f) instanceof String) {
							map
									.put(QName.valueOf(f), (String) this
											.getField(f));
						}
					}
				}

			// Date型
			if (FIELD_DATES != null)
				for (String f : FIELD_DATES) {
					if (this.getFields().containsKey(f)) {
						if (this.getField(f) instanceof Date) {
							map.put(QName.valueOf(f), DateUtils.dat2str(
									(Date) this.getField(f), true));
						} else if (this.getField(f) instanceof String) {
							map
									.put(QName.valueOf(f), (String) this
											.getField(f));
						}
					}
				}

			return map;
		} catch (Exception e) {
			throw new SinoBPMException("创建JSON对象出现错误。");
		}
	}

	/**
	 * 从映射对象中设置对象
	 * 
	 * @param jo
	 * @throws SinoBPMException
	 */
	@Override
	public void fromMap(Map<QName, String> map) throws SinoBPMException {
		try {

			// Boolean型
			if (FIELD_BOOLEANS != null)
				for (String f : FIELD_BOOLEANS) {
					QName fq = QName.valueOf(f);
					if (map.containsKey(fq)) {
						String str = map.get(fq);
						if (Const.isEmpty(str)) {
							str = "false";
						}
						this.addField(f, Boolean.valueOf(str));
					}
				}

			// 字符串型
			if (FIELD_STRINGS != null)
				for (String f : FIELD_STRINGS) {
					QName fq = QName.valueOf(f);
					if (map.containsKey(fq)) {
						this.addField(f, map.get(fq));
					}
				}

			// Date型
			if (FIELD_DATES != null)
				for (String f : FIELD_DATES) {
					QName fq = QName.valueOf(f);
					if (map.containsKey(fq)) {
						String str = map.get(fq);
						if (!Const.isEmpty(str)) {
							this.addField(f, DateUtils.str2dat(str,
									Const.GENERALIZED_DATE_TIME_FORMAT_MILLIS));
						}
					}
				}

		} catch (Exception e) {
			throw new SinoBPMException("创建JSON对象出现错误。");
		}
	}

}
